# coding:utf-8
import random
from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django_redis import get_redis_connection
from web.models import UserInfo
from django.conf import settings
from utils.tencent_sms import send_sms_single
from utils.encrypt import set_md5
from web.forms.bootstrap import BootstrapForm


# 注册
class RegisterModelForm(BootstrapForm, forms.ModelForm):
    password = forms.CharField(
        label='密码',
        min_length=8,
        max_length=32,
        widget=forms.PasswordInput(),
        error_messages={
            'min_length': '密码长度不能小于8个字符',
            'max_length': '密码长度不能大于32个字符',
        }
    )
    confirm_password = forms.CharField(
        label='确认密码',
        min_length=8,
        max_length=32,
        widget=forms.PasswordInput(),
        error_messages={
            'min_length': '确认密码长度不能小于8个字符',
            'max_length': '确认密码长度不能大于32个字符',
        }
    )
    phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^1[3-9]\d{9}$', '请输入正确的手机号')])
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    class Meta:
        model = UserInfo
        fields = ['username', 'password', 'confirm_password', 'email', 'phone', 'code']

    def clean_username(self):
        username = self.cleaned_data['username']
        exists = UserInfo.objects.filter(username=username).exists()
        if exists:
            self.add_error('username', '该用户名已被注册')
            # raise ValidationError('该用户名已被注册')
        return username

    def clean_email(self):
        email = self.cleaned_data['email']
        exists = UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('该邮箱已被使用')
        return email

    def clean_password(self):
        pwd = self.cleaned_data['password']
        return set_md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data['password']
        confirm_pwd = set_md5(self.cleaned_data['confirm_password'])
        if pwd != confirm_pwd:
            raise ValidationError('两次输入的密码不一致')
        return confirm_pwd

    def clean_phone(self):
        phone = self.cleaned_data['phone']
        exists = UserInfo.objects.filter(phone=phone).exists()
        if exists:
            raise ValidationError('该手机号已被注册')
        return phone

    def clean_code(self):
        code = self.cleaned_data['code']
        phone = self.cleaned_data['phone']
        conn = get_redis_connection()
        redis_code = conn.get(phone)
        if not redis_code:
            raise ValidationError('无效验证码，请重新获取')
        redis_str_code = redis_code.decode('utf-8')
        if code != redis_str_code:
            raise ValidationError('验证码错误')
        return code


# 短信验证码发送
class SendSmsForm(BootstrapForm, forms.Form):
    phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^1[3-9]\d{9}$', '请输入正确的手机号')])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_phone(self):
        phone = self.cleaned_data['phone']
        tpl = self.request.GET.get('tpl')
        tpl_id = settings.TENCENT_SMS_TEMPLATE.get(tpl)
        if not tpl_id:
            raise ValidationError('短信发送失败，没有该短信模板')
        exists = UserInfo.objects.filter(phone=phone).exists()
        if tpl == 'login':
            if not exists:
                raise ValidationError('该手机号未注册')
        else:
            if exists:
                raise ValidationError('该手机号已被注册')
        code = random.randint(1000, 9999)
        sms = send_sms_single('13438229772', tpl_id, [code, ])
        if sms['result'] != 0:
            raise ValidationError("短信发送失败，{}".format(sms['errmsg']))
        conn = get_redis_connection()
        conn.set(phone, code, 300)
        return phone


# 短信验证码登录
class LoginSmsForm(BootstrapForm, forms.Form):
    phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^1[3-9]\d{9}$', '请输入正确的手机号')])
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    def clean_phone(self):
        phone = self.cleaned_data['phone']
        user_obj = UserInfo.objects.filter(phone=phone).first()
        if not user_obj:
            self.add_error('phone', '不存在该用户')
        return user_obj

    def clean_code(self):
        code = self.cleaned_data['code']
        user_obj = self.cleaned_data['phone']  # clean_phone返回的是用户对象
        phone = user_obj.phone
        if not user_obj:  # 用户不存在
            return code

        conn = get_redis_connection()
        redis_code = conn.get(phone)
        if not redis_code:
            raise ValidationError('无效验证码，请重新获取')
        redis_str_code = redis_code.decode('utf-8')
        if code.strip() != redis_str_code:
            raise ValidationError('验证码错误')
        return code


# 用户名密码登录
class LoginForm(BootstrapForm, forms.Form):
    username = forms.CharField(max_length=32, label='手机号或邮箱')
    password = forms.CharField(max_length=32, widget=forms.PasswordInput(render_value=True), label='密码')
    code = forms.CharField(max_length=32, label='验证码')

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_password(self):
        pwd = self.cleaned_data['password']
        return set_md5(pwd)

    def clean_code(self):
        code = self.cleaned_data['code']
        session_code = self.request.session.get('img_code')
        if not session_code:
            raise ValidationError('验证码已过期，请点击验证码重新获取')
        if code.strip().upper() != session_code.upper():
            raise ValidationError('验证码错误')
        return code
